package cc.edge2.sns;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cc.edge2.sns.commons.PMF;
import cc.edge2.sns.models.SNSUser;
import cc.edge2.sns.services.GetDiaryListService;
import cc.edge2.sns.services.GetDiaryService;
import cc.edge2.sns.services.GetFriendListService;
import cc.edge2.sns.services.GetMyProfileService;
import cc.edge2.sns.services.GetRecentFriendDiaryListService;
import cc.edge2.sns.services.GetUserProfileService;
import cc.edge2.sns.services.RegisterFriendService;
import cc.edge2.sns.services.ReleaseFriendService;
import cc.edge2.sns.services.SaveDiaryService;
import cc.edge2.sns.services.SaveProfileService;
import cc.edge2.sns.services.SaveTestUserService;
import cc.edge2.sns.services.SearchUserService;

import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

@SuppressWarnings("serial")
public class EdgeSNSServlet extends HttpServlet {
	private static final Logger log = Logger.getLogger(EdgeSNSServlet.class.getName());
	private static Map<String, Object> serviceMap = new HashMap<String, Object>();
	
	static {
		serviceMap.put("getMyProfile", new GetMyProfileService());
		serviceMap.put("saveProfile", new SaveProfileService());
		serviceMap.put("saveDiary", new SaveDiaryService());
		serviceMap.put("getDiaryList", new GetDiaryListService());
		serviceMap.put("getDiary", new GetDiaryService());
		serviceMap.put("searchUser", new SearchUserService());
		serviceMap.put("saveTestUser", new SaveTestUserService());
		serviceMap.put("getUserProfile", new GetUserProfileService());
		serviceMap.put("registerFriend", new RegisterFriendService());
		serviceMap.put("getFriendList", new GetFriendListService());
		serviceMap.put("releaseFriend", new ReleaseFriendService());
		serviceMap.put("getRecentFriendDiaryList", new GetRecentFriendDiaryListService());
	}
	
	public void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws IOException {

		//ログイン状態かをチェックしログインしていなければログイン画面に遷移
		UserService userService = UserServiceFactory.getUserService();
        if (req.getUserPrincipal() == null) {
        	resp.sendRedirect(userService.createLoginURL(req.getRequestURI()));
        	return;
        }		
		log.info(req.getRequestURI());
        //サービス名の取得
		String serviceName = null;
		if("/edgesns/".length() <= req.getRequestURI().length()) {
			serviceName = req.getRequestURI().substring("/edgesns/".length());
		}
		
		SNSUser user = (SNSUser)req.getSession(true).getAttribute("user");
		//ユーザ情報を取得する。はじめてアクセスするユーザの場合はユーザ情報を作成する。
		if(user == null) {
			user = getOrCreateUser(userService.getCurrentUser());
		}
		
		Object service = serviceMap.get(serviceName);
		if(service == null) {
//			resp.getWriter().println(serviceName);

			//存在しないサービスであれば初期画面に遷移(仮実装)
			try {
				req.getRequestDispatcher("/index2.html").forward(req, resp);
			} catch (ServletException e) {
				e.printStackTrace();
			}
//			resp.sendRedirect("/index2.html");

		} else {
			String result = "";
			try {
				Class[] classes = {Map.class, SNSUser.class};
				Method method = service.getClass().getMethod("execute", classes);
				Map reqMap = req.getParameterMap();
				Map map = new HashMap();
				Iterator<String> it = reqMap.keySet().iterator();
				for(;it.hasNext();) {
					String key = it.next();
					result += ((String[])reqMap.get(key))[0];
					map.put(key, ((String[])reqMap.get(key))[0]);
				}
				result = (String)method.invoke(service, map, user);
			} catch (Exception e) {
				e.printStackTrace();
			}
			
			resp.setContentType("text/plain; charset=UTF-8");
			resp.getWriter().println(result);
		}
		
	}

	private SNSUser getOrCreateUser(User currentUser) {
		
		PersistenceManager pm = PMF.get().getPersistenceManager();
		
		javax.jdo.Query query = pm.newQuery(SNSUser.class);
		query.setFilter("email == emailParam");
		query.declareParameters("String emailParam");
		SNSUser user = null;
		try {
			List<SNSUser> results = (List<SNSUser>)query.execute(currentUser.getEmail());
			if(results.size() > 0) {
				user = results.get(0);
			}
		} finally {
			query.closeAll();
		}
		
		if(user != null) {
			pm.close();
			return user;
		}
		
		user = new SNSUser(currentUser);
		try { 
			pm.makePersistent(user);
		} finally {
			pm.close();
		}
		return user;
	}
	
}
